package com.atguigu.crowd.util;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.comm.ResponseMessage;
import com.aliyun.oss.model.PutObjectResult;
import com.atguigu.crowd.constant.CrowdConstant;
import org.junit.Test;

import javax.servlet.http.HttpServletRequest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * 工具类
 *
 * @author cyb315
 * @create 2021-10-18 17:13
 */
public class CrowdUtil {


    /**
     * 判断请求是否是ajax请求的方法
     *
     * @param request 当前请求对象
     * @return 是true否false
     */
    public static boolean judgeRequestType(HttpServletRequest request) {

        // 获取请求头信息，用于判断
        String acceptInfomation = request.getHeader("Accept");
        String xRequestInfomation = request.getHeader("X-Requested-With");

        return (acceptInfomation != null && acceptInfomation.length() > 0 && acceptInfomation.contains("application/json")) ||
                (xRequestInfomation != null && xRequestInfomation.length() > 0 && xRequestInfomation.equals("XMLHttpRequest"));

    }


    /**
     * 对明文字符串进行MD5加密
     *
     * @param source 传入的源明文字符串
     * @return 加密后的结果
     */
    public static String md5(String source) {

        // 1.判断source是否有效（防止出现空指针异常）
        if (source == null || source.length() == 0) {

            // 如果不是有效的字符串就抛出异常
            throw new RuntimeException(CrowdConstant.MESSAGE_STRING_INVALIDATE);
        }

        try {
            // 2.获取MessageDigest对象
            String algorithm = "md5";
            MessageDigest messageDigest = MessageDigest.getInstance(algorithm);

            // 3.获取源明文字符串对应的字节数组
            byte[] input = source.getBytes();

            // 4.执行加密，生成加密后的字节数组
            byte[] output = messageDigest.digest(input);

            // 5.创建加密结果对应的BigInteger对象
            // signum控制正负，-1负数，0是0,1是正数
            int signum = 1;
            BigInteger bigInteger = new BigInteger(signum, output);

            // 6.按照16进制将bigInteger的值转换为字符串
            // 指定进制数16
            int radix = 16;
            String encoded = bigInteger.toString(radix).toUpperCase();

            // 7.返回加密结果
            return encoded;

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        // 8.出现异常返回null值
        return null;
    }

    /**
     * 专门负责上传文件到 OSS 服务器的工具方法
     *
     * @param endpoint
     * @param accessKeyId
     * @param accessKeySecret
     * @param inputStream     要上传的文件的输入流
     * @param bucketName
     * @param bucketDomain
     * @param originalName    要上传的文件的原始文件名
     * @return
     */
    public static ResultEntity<String> uploadFileToOss(
            String endpoint,
            String accessKeyId,
            String accessKeySecret,
            InputStream inputStream,
            String bucketName,
            String bucketDomain,
            String originalName
    ) {

        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // 生成上传文件的目录（每天一个目录）
        String folderName = new SimpleDateFormat("yyyyMMdd").format(new Date());

        // 生成上传文件在 OSS 服务器上保存时的文件名
        String fileMainName = UUID.randomUUID().toString().replace("-", "");

        // 从原始文件名中获取文件扩展名
        String extensionName = originalName.substring(originalName.lastIndexOf("."));

        // 使用目录、文件主体名称、文件扩展名称拼接得到对象名称
        String objectName = folderName + "/" + fileMainName + extensionName;

        try {
            // 调用 OSS 客户端对象的方法上传文件并获取响应结果数据
            PutObjectResult putObjectResult = ossClient.putObject(bucketName, objectName, inputStream);

            // 从响应结果中获取具体响应消息
            ResponseMessage responseMessage = putObjectResult.getResponse();

            // 根据响应状态码判断请求是否成功
            if (responseMessage == null) {
                // 请求成功
                // 拼接访问刚刚上传的文件的路径
                String ossFileAccessPath = bucketDomain + "/" + objectName;

                // 当前方法返回成功,并返回文件访问路径
                return ResultEntity.successWithData(ossFileAccessPath);

            } else {
                // 请求失败
                // 获取响应状态码
                int statusCode = responseMessage.getStatusCode();

                // 如果请求没有成功，获取错误消息
                String errorMessage = responseMessage.getErrorResponseAsString();

                // 当前方法返回失败
                return ResultEntity.failed(" 当前响应状态码 =" + statusCode + " 错误消息 =" + errorMessage);
            }

        } catch (Exception e) {

            e.printStackTrace();
            // 当前方法返回失败
            return ResultEntity.failed(e.getMessage());

        } finally {

            if (ossClient != null) {
                // 关闭 OSSClient
                ossClient.shutdown();
            }

        }
    }

}
